iT邦幫忙

2023 iThome 鐵人賽

DAY 23
1
SideProject30

製作適用於網頁的台灣登山地圖系列 第 23

[Day23] Maplibre Style 中的表達式

  • 分享至 

  • xImage
  •  

前言

之前在 Day14 示範過使用 Maplibre Style 新增兩個圖層,在前端呈現簡單的樣式。不過相信在前幾天的範例中,讀者應該也發現到屬性值可以不單純是數字或文字,而是包含在 JSON Array 內的各種表達式。

表達式的說明文件被紀錄在 expressions 一節。在 layers 的各個圖層中,被包含在 layoutpaint 內的屬性值都適用表達式,用以更加靈活的適用不同狀況,例如:

  1. 在不同的縮放層級下,有不同的顏色/長度/寬度/文字內容
  2. 根據物件(feature)的屬性,有不同的顏色/長度/寬度值/文字內容
  3. 篩選哪些物件可以被渲染

表達式都是以 JSON Array 的型式存在,並在第一個元素賦予關鍵字。以下就來介紹幾個常用的表達式,並搭配實際範例:

資料表達式 (Data expressions)

可以使用 get, has, id 等關鍵字來取得或比較物件屬性,例如下面要決定圓圈顏色的表達式中:

{
    "circle-color": [
        "rgb",
        // red is higher when feature.properties.temperature is higher
        ["get", "temperature"],
        // green is always zero
        0,
        // blue is higher when feature.properties.temperature is lower
        ["-", 100, ["get", "temperature"]]
    ]
}

["get", "temperature"] 即代表取得物件 temperature 的屬性值,而 ["-", 100, ["get", "temperature"]] 則可以拆成兩部分來看:

  1. ["-", 100, X]: 100 - X
  2. X=["get", "temperature"]: X=temperature

因此可以知道,其涵意是 100-溫度值

而最外層由 rgb 開頭的 Array 也不難懂。雖然我們還沒學到該關鍵字,但後面接上三個表達式,很明顯就是要決定 RGB 值。所以上面範例中的圓圈值,一般來說就是 rgb(溫度,0,100-溫度) 的意思。(所以溫度為100時,顏色應該是暗紅色)

縮放層級表達式 (Camera expressions)

根據地圖的相機伸縮,Maplibre Style 會利用不同的 zoom 值來決定屬性。["zoom"] 這個表達式可以取得目前的縮放層級。

舉例來說,若我們需要依不同縮放層級調整圓圈大小,則可以使用:

{
    "circle-radius": [
        "interpolate", ["linear"], ["zoom"],
        // zoom is 5 (or less) -> circle radius will be 1px
        5, 1,
        // zoom is 10 (or greater) -> circle radius will be 5px
        10, 5
    ]
}

在使用關鍵字 interpolate 的情況下,圓圈半徑以設定的區間線性變化。從上面的設定來說,在 zoom=5 到 zoom=10 這個區間,其值會由 1px 線性變化到 5px,而超出區間的數值則保持不變。因此,我們可以用表格來表示半徑的變化:

zoom 半徑
... 1
4 1
5 1
6 1.8
7 2.6
8 3.4
9 4.2
10 5
11 5
12 5
... 5

渲染結果如下,可以看到隨著縮放層級的增加,紅色的圓圈也逐漸變大,非常符合直覺:
zoom

判斷式

用不同關鍵字新增判斷邏輯,只要有點其它程式語言的概念,應該不難理解。例如,以下的關鍵字用於回傳布林值:

  • !
  • !=
  • <
  • <=
  • ==
  • >
  • >=

舉例來說: ["<=", 1, 2] 會等同於 (1 <= 2),因此會回傳 false

而條件式就有各種參數了。case表達式提供 if/then/else 的邏輯。而 match 則類似於其它語言中的 switch,可以為各種輸入值指定回傳值,並給定預設值。條件式可使用以下的關鍵字:

all

所有參數都為 true 才會回傳 true,例如:["all", ["==", 1, 1], [">", 3, 1]] 會回傳 true

any

任一參數為 true 就會回傳 true

case

兩個參數為一組case,若前一個參數回傳 true 則回傳下一個參數。若所有組別都回傳 false,則使用預設值(最後一個參數)。例如:

["case",
  ["==" ["get", "gender"], "male"], "男生",        <----一組case
  ["==" ["get", "gender"], "female"], "女生",      <----一組case
  "性別不明"    <----預設值
]

會依物件的 gender 屬性來返回 男生, 女生, 性別不明等三個值。

match

case 的差別在於,第一個參數是輸入值,用以和兩個一組的參數進行比對。因此上面的例子可以改寫為:

["match",
  ["get", "gender"],  <----輸入值
  "male", "男生",      <----一組 match
  "female", "女生",    <----一組 match
  "性別不明"           <----預設值
]

其它還有 whthin(用於比對地圖上的相對位置) 和 coalesce 等條件式,不過先掌握上面幾個就很夠用了。

其它關鍵字

簡單來說,Maplibre Style Expression 就是要使用 JSON 格式來模擬常用程式語言中的函式和各種運算符號。因此許多想得到想不到的關鍵字都可以在說明頁面中找到。

例如數學符號的 abs, +, -, *, /、字串的操作 concat, downcase, upcase等。使用者沒必要全部記住,只要在需要使用時查閱文件即可,在此就不一一列舉。

結語

表達式在使用上相當接近 lisp 的括號表達式,它們對 Style 中各種屬性的運算,也有點像 SASS 與 CSS 的關係。

透過表達式,製圖者可以為渲染結果做出更多精細控制,讓畫面上更加協調。也因此會需要向量圖磚中,各種物件的屬性來搭配才能發揮威力。所以在製作專門用途的地圖時, tile schema 和 Style 的設計會需要互相考量,依需求持續進行調整。


上一篇
[Day22] 修改登山路徑
下一篇
[Day24] 使用 Sprite 來呈現圖示
系列文
製作適用於網頁的台灣登山地圖25
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言